﻿
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.ExceptionHandling.Localization;
using Volo.Abp.Http;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;

namespace Leo.Core.HttpApi.Host.Filters
{
    public class AbpBaseExceptionToErrorInfoConverter : DefaultExceptionToErrorInfoConverter
    {
        public AbpBaseExceptionToErrorInfoConverter(
          IOptions<AbpExceptionLocalizationOptions> localizationOptions,
          IStringLocalizerFactory stringLocalizerFactory,
          IStringLocalizer<AbpExceptionHandlingResource> stringLocalizer,
          IServiceProvider serviceProvider) : base(
              localizationOptions,
              stringLocalizerFactory,
              stringLocalizer,
              serviceProvider)
        {

        }
        protected override void TryToLocalizeExceptionMessage(Exception exception, RemoteServiceErrorInfo errorInfo)
        {
            if (exception is ILocalizeErrorMessage localizeErrorMessageException)
            {
                using (var scope = ServiceProvider.CreateScope())
                {
                    errorInfo.Message = localizeErrorMessageException.LocalizeMessage(new LocalizationContext(scope.ServiceProvider));
                }

                return;
            }

            if (!(exception is IHasErrorCode exceptionWithErrorCode))
            {
                return;
            }

            // let's system support no many language of exception message
            if (exceptionWithErrorCode.Code.IsNullOrWhiteSpace() ||
                !exceptionWithErrorCode.Code.Contains(":"))
            {
                errorInfo.Message = exceptionWithErrorCode.Code.Split(':')[0];
                return;
            }

            var codeNamespace = exceptionWithErrorCode.Code.Split(':')[0];

            var localizationResourceType = LocalizationOptions.ErrorCodeNamespaceMappings.GetOrDefault(codeNamespace);
            if (localizationResourceType == null)
            {
                return;
            }

            var stringLocalizer = StringLocalizerFactory.Create(localizationResourceType);
            var localizedString = stringLocalizer[exceptionWithErrorCode.Code];
            if (localizedString.ResourceNotFound)
            {
                return;
            }

            var localizedValue = localizedString.Value;

            if (exception.Data != null && exception.Data.Count > 0)
            {
                foreach (var key in exception.Data.Keys)
                {
                    localizedValue = localizedValue.Replace("{" + key + "}", exception.Data[key]?.ToString());
                }
            }

            errorInfo.Message = localizedValue;
        }
    }
}
